#include <QAction>
#include <QString>
#include <QMessageBox>
#include <QApplication>
#include <QMenuBar>
#include <QStatusBar>
#include <QLabel>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QDebug>
#include <QHostAddress>
#include <QThread>
#include <QStackedWidget>
#include <QTableView>
#include <QPushButton>
#include <QLineEdit>
#include <QGroupBox>
#include <QDateEdit>
#include <QValidator>
#include <QRegExp>

#include "LoginDialog.hpp"
#include "Client.hpp"

#include "MainWindow.hpp"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    m_findWidget(nullptr),
    m_statisticsTreeView(nullptr)
{
    actionInit();
    menuBarInit();
    statusBarInit();
    stackedWidgetInit();

    this->setWindowTitle(trUtf8("Автоинспектор Онлайн"));
    this->showMaximized();

    m_client = new Client();
    m_networkThread = new QThread(this);
    m_client->moveToThread(m_networkThread);

    m_networkThread->start();
    connect(this, SIGNAL(connectToHost(QString,quint16)),
            m_client, SLOT(connectToHost(QString,quint16)));
    connect(this, SIGNAL(authorization(QString,QString)),
            m_client, SLOT(authorization(QString,QString)));
    connect(m_client, SIGNAL(errorForHumans(QString)),
            this, SLOT(errorDisplay(QString)));
    connect(m_client, SIGNAL(connected()),
            this, SLOT(connected()));
    connect(m_client, SIGNAL(settingsUserRight(quint16)),
            this, SLOT(settings(quint16)));
    connect(this, SIGNAL(searchOnNextMonth(QDate)),
            m_client, SLOT(allTransport()));
    connect(m_logoutAction, SIGNAL(triggered()),
            m_client, SLOT(disconnectFromHost()));
}

MainWindow::~MainWindow()
{

}

void MainWindow::closeEvent(QCloseEvent *event)
{
    m_logoutAction->trigger();
    m_networkThread->exit();
    QMainWindow::closeEvent(event);
}

void MainWindow::actionInit()
{
    m_aboutProgramAction =
            new QAction(trUtf8("О программе"), this);
    connect(m_aboutProgramAction, SIGNAL(triggered()),
            this, SLOT(aboutProgram()));

    m_aboutQtAction =
            new QAction(trUtf8("О Qt"), this);
    connect(m_aboutQtAction, SIGNAL(triggered()),
            qApp, SLOT(aboutQt()));

    m_closeAction =
            new QAction(trUtf8("Закрыть"), this);
    connect(m_closeAction, SIGNAL(triggered()),
            this, SLOT(close()));

    m_findAction =
            new QAction(trUtf8("Поиск"), this);
    m_findAction->setVisible(false);
    connect(m_findAction, SIGNAL(triggered()),
            this, SLOT(findWidgetShow()));

    m_statisticsAction =
            new QAction(trUtf8("Статистика"), this);
    m_statisticsAction->setVisible(false);
    connect(m_statisticsAction, SIGNAL(triggered()),
            this, SLOT(statisticsWidgetShow()));

    m_loginAction =
            new QAction(trUtf8("Вход"), this);
    connect(m_loginAction, SIGNAL(triggered()),
            this, SLOT(loginWindowShow()));

    m_logoutAction =
            new QAction(trUtf8("Выход"), this);
    connect(m_logoutAction, SIGNAL(triggered()),
            this, SLOT(logout()));

    m_usersAction =
            new QAction(trUtf8("Пользователи"), this);
    m_usersAction->setVisible(false);
    connect(m_usersAction, SIGNAL(triggered()),
            this, SLOT(usersWidgetShow()));

}

void MainWindow::menuBarInit()
{
    m_menuBar = new QMenuBar(this);
    m_mainAction = m_menuBar->addMenu(trUtf8("Главная"));
    m_mainAction->addAction(m_loginAction);
    m_mainAction->addAction(m_logoutAction);
    m_mainAction->addSeparator();
    m_mainAction->addAction(m_closeAction);

    m_operationAction = m_menuBar->addMenu(trUtf8("Операции"));
    m_operationAction->addAction(m_findAction);
    m_operationAction->addAction(m_statisticsAction);
    m_operationAction->addAction(m_usersAction);
    m_operationAction->setDisabled(true);

    m_aboutAction = m_menuBar->addMenu(trUtf8("Помощь"));
    m_aboutAction->addAction(m_aboutProgramAction);
    m_aboutAction->addAction(m_aboutQtAction);

    this->setMenuBar(m_menuBar);
}

void MainWindow::statusBarInit()
{
    this->statusBar()->addPermanentWidget(new QLabel(QChar(0x00A9)
                                                     + trUtf8("СПбГУВК, 2012"), this));
    this->statusBar()->showMessage(trUtf8("Started"));
}

void MainWindow::stackedWidgetInit()
{
    m_stackedWidget = new QStackedWidget(this);
    m_stackedWidget->addWidget(new QWidget(m_stackedWidget));
    this->setCentralWidget(m_stackedWidget);
}

void MainWindow::findWidgetCreate()
{
    /*================================================*/
    /*==>>> Create findWidget and inside widgets <<<==*/
    /*================================================*/
    m_findWidget = new QWidget(m_stackedWidget);

    //Create leftBar
    QWidget *leftBarWidget = new QWidget(m_findWidget);
    leftBarWidget->setMinimumWidth(100);
    leftBarWidget->setMaximumWidth(200);

    //Create first group for searching by current date on next month
    QGroupBox *groupOnNextMonth = new QGroupBox(trUtf8("На ближайший месяц"),
                                                leftBarWidget);
    QVBoxLayout *onNextMonthLayout = new QVBoxLayout(groupOnNextMonth);
    onNextMonthLayout->addWidget(new QLabel(trUtf8("Тек. дата:"),
                                            groupOnNextMonth));
    m_currentDateEdit = new QDateEdit(groupOnNextMonth);
    m_currentDateEdit->setReadOnly(true);
    m_currentDateEdit->setButtonSymbols(QDateEdit::NoButtons);
    m_currentDateEdit->setDate(QDate::currentDate());
    onNextMonthLayout->addWidget(m_currentDateEdit);
    m_byNextMonthFindButton = new QPushButton(trUtf8("Поиск"),
                                              groupOnNextMonth);
    QHBoxLayout *nextMonthFindButtonLayout = new QHBoxLayout(groupOnNextMonth);
    nextMonthFindButtonLayout->addStretch();
    nextMonthFindButtonLayout->addWidget(m_byNextMonthFindButton);
    onNextMonthLayout->addLayout(nextMonthFindButtonLayout);
    groupOnNextMonth->setLayout(onNextMonthLayout);

    //Second group for searching by borad number template
    QGroupBox *groupByBoardNumber = new QGroupBox(trUtf8("По шаблону бортового номера"),
                                                  leftBarWidget);
    QVBoxLayout *byBoardNumberLayout = new QVBoxLayout(groupByBoardNumber);
    byBoardNumberLayout->addWidget(new QLabel(trUtf8("Бортовой номер:"),
                                              groupByBoardNumber));
    m_boardNumberLineEdit = new QLineEdit(groupByBoardNumber);
    m_boardNumberLineEdit->setMaxLength(50);
    //m_boardNumberLineEdit->setValidator(new QRegExpValidator(QRegExp("(\\w*|\\**|\\\\*)*")));
    byBoardNumberLayout->addWidget(m_boardNumberLineEdit);
    QHBoxLayout *byBoardNumberButtonLayout = new QHBoxLayout(groupByBoardNumber);
    byBoardNumberButtonLayout->addStretch();
    m_byBoardNumFindButton = new QPushButton(trUtf8("Поиск"),
                                             groupByBoardNumber);
    byBoardNumberButtonLayout->addWidget(m_byBoardNumFindButton);
    byBoardNumberLayout->addLayout(byBoardNumberButtonLayout);
    groupByBoardNumber->setLayout(byBoardNumberLayout);

    //Third group for searching by release period
    QGroupBox *groupByReleasePeriod = new QGroupBox(trUtf8("По периоду выпуска"),
                                                    leftBarWidget);
    QVBoxLayout *byReleasePeriodLayout = new QVBoxLayout(groupByReleasePeriod);
    byReleasePeriodLayout->addWidget(new QLabel(trUtf8("Начало периода:"),
                                                groupByReleasePeriod));
    m_startReleaseDateEdit = new QDateEdit(groupByReleasePeriod);
    m_startReleaseDateEdit->setDisplayFormat("yyyy");
    m_startReleaseDateEdit->setCurrentSection(QDateEdit::YearSection);
    m_startReleaseDateEdit->setMinimumDate(QDate(1900,1,1));
    byReleasePeriodLayout->addWidget(m_startReleaseDateEdit);
    byReleasePeriodLayout->addWidget(new QLabel(trUtf8("Конец периода:"),
                                                groupByReleasePeriod));
    m_endReleaseDateEdit = new QDateEdit(groupByReleasePeriod);
    m_endReleaseDateEdit->setDisplayFormat("yyyy");
    m_endReleaseDateEdit->setCurrentSection(QDateEdit::YearSection);
    m_endReleaseDateEdit->setDate(QDate::currentDate());
    m_endReleaseDateEdit->setMaximumDate(QDate::currentDate());
    byReleasePeriodLayout->addWidget(m_endReleaseDateEdit);
    QHBoxLayout *byReleasePeriodButtonLayout = new QHBoxLayout(groupByReleasePeriod);
    byReleasePeriodButtonLayout->addStretch();
    m_byReleasePeriodFindButton = new QPushButton(trUtf8("Поиск"),
                                                  groupByReleasePeriod);
    byReleasePeriodButtonLayout->addWidget(m_byReleasePeriodFindButton);
    byReleasePeriodLayout->addLayout(byReleasePeriodButtonLayout);
    groupByReleasePeriod->setLayout(byReleasePeriodLayout);
    connect(m_endReleaseDateEdit, SIGNAL(dateChanged(QDate)),
            this, SLOT(setMaximumDate(QDate)));
    connect(m_startReleaseDateEdit, SIGNAL(dateChanged(QDate)),
            this, SLOT(setMinimumDate(QDate)));

    QVBoxLayout *mainLeftBarLayout = new QVBoxLayout(leftBarWidget);
    //Add widgets in leftBar
    mainLeftBarLayout->addWidget(groupOnNextMonth);
    mainLeftBarLayout->addSpacing(10);
    mainLeftBarLayout->addWidget(groupByBoardNumber);
    mainLeftBarLayout->addSpacing(10);
    mainLeftBarLayout->addWidget(groupByReleasePeriod);
    mainLeftBarLayout->addStretch();
    leftBarWidget->setLayout(mainLeftBarLayout);

    //Create table for search result view
    m_transportTableView = new QTableView(m_findWidget);

    QHBoxLayout *mainLayout = new QHBoxLayout(m_findWidget);
    mainLayout->addWidget(leftBarWidget);
    mainLayout->addWidget(m_transportTableView);
    m_findWidget->setLayout(mainLayout);
    m_stackedWidget->addWidget(m_findWidget);

    connect(m_byNextMonthFindButton, SIGNAL(clicked()),
            this, SLOT(searchOnNextMonthClicked()));
}

void MainWindow::settingsForNotAuthorised()
{
    this->m_operationAction->setDisabled(true);
    this->m_findAction->setVisible(false);
    this->m_statisticsAction->setVisible(false);
    this->m_usersAction->setVisible(false);
    this->m_loginAction->setEnabled(true);
    this->m_logoutAction->setDisabled(true);
    this->m_stackedWidget->setCurrentIndex(0);
}

void MainWindow::settingsForAdmin()
{
    this->m_operationAction->setDisabled(false);
    this->m_findAction->setVisible(true);
    this->m_statisticsAction->setVisible(true);
    this->m_usersAction->setVisible(true);
    this->findWidgetShow();
}

void MainWindow::settingsForOperator()
{
    this->m_operationAction->setDisabled(false);
    this->m_findAction->setVisible(true);
    this->m_statisticsAction->setVisible(true);
    this->m_usersAction->setVisible(false);
    this->findWidgetShow();
}

void MainWindow::settingsForRegistrator()
{
    this->m_operationAction->setDisabled(false);
    this->m_findAction->setVisible(true);
    this->m_statisticsAction->setVisible(true);
    this->m_usersAction->setVisible(false);
    this->findWidgetShow();
}

void MainWindow::aboutProgram()
{
    QMessageBox::about(this, trUtf8("About"),
                       trUtf8("<html><body><p>Программа \"Автоинспектор Онлайн\" разработана<br>"
                              "студентами гр. ИС-41 Уласень И. и Черниковым А.А.<br>"
                              "под руководством Балсы А.Р.</p>"
                              "<p align = \"right\">")
                       + QChar(0x00A9)
                       + trUtf8("СПбГУВК, 2012</p></body></html>"));
}

void MainWindow::loginWindowShow()
{
    LoginDialog loginDialog(this);
    if(loginDialog.exec()) {
        qDebug() << "IP:" << loginDialog.getIP();
        qDebug() << "Port:" << loginDialog.getPort();
        qDebug() << "Name:" << loginDialog.getName();
        qDebug() << "Password" << loginDialog.getPassword();

        m_loginAction->setDisabled(true);

        emit connectToHost(loginDialog.getIP(), loginDialog.getPort().toUInt());
        emit authorization(loginDialog.getName(), loginDialog.getPassword());
    }
}

void MainWindow::logout()
{
    settingsForNotAuthorised();
}

void MainWindow::errorDisplay(QString error)
{
    QMessageBox::critical(this, trUtf8("Ошибка!"),
                          error, QMessageBox::Ok);
}

void MainWindow::connected()
{

}

void MainWindow::settings(quint16 userRight)
{
    m_loginAction->setDisabled(true);
    m_logoutAction->setDisabled(false);
    switch (userRight) {
    case ADMIN:
        settingsForAdmin();
        break;

    case OPERATOR:
        settingsForOperator();
        break;

    case REGISTRATOR:
        settingsForRegistrator();
        break;

    default:
        settingsForNotAuthorised();
        break;
    }
}

void MainWindow::findWidgetShow()
{
    if (!m_findWidget) {
        findWidgetCreate();
    }
    this->m_stackedWidget->setCurrentWidget(m_findWidget);
}

void MainWindow::usersWidgetShow()
{
}

void MainWindow::statisticsWidgetShow()
{
}

void MainWindow::setMinimumDate(QDate minDate)
{
    m_endReleaseDateEdit->setMinimumDate(minDate);
}

void MainWindow::setMaximumDate(QDate maxDate)
{
    m_startReleaseDateEdit->setMaximumDate(maxDate);
}

void MainWindow::searchOnNextMonthClicked()
{
    emit searchOnNextMonth(m_currentDateEdit->date());
}

